CM3D2 Converter.tex_export

  1import bpy
  2import os
  3import struct
  4from . import common
  5from . import compat
  6from .translations.pgettext_functions import *
  7
  8
  9@compat.BlRegister()
 10class CNV_OT_export_cm3d2_tex(bpy.types.Operator):
 11    bl_idname = 'image.export_cm3d2_tex'
 12    bl_label = "texファイルを保存"
 13    bl_description = "CM3D2で使用されるテクスチャファイル(.tex)として保存します"
 14    bl_options = {'REGISTER'}
 15
 16    filepath = bpy.props.StringProperty(subtype='FILE_PATH')
 17    filename_ext = ".tex"
 18    filter_glob = bpy.props.StringProperty(default="*.tex", options={'HIDDEN'})
 19
 20    is_backup = bpy.props.BoolProperty(name="ファイルをバックアップ", default=True, description="ファイルに上書きする場合にバックアップファイルを複製します")
 21
 22    version = bpy.props.EnumProperty(
 23        name="ファイルバージョン",
 24        items=[
 25            ('1011', '1011', 'COM3D2 1.13 or later', 'NONE', 0),
 26            ('1010', '1010', 'CM3D2 1.49 ~ or COM3D2', 'NONE', 1),
 27            ('1000', '1000', '旧フォーマット', 'NONE', 2),
 28        ], default='1010')
 29    path = bpy.props.StringProperty(name="パス", default=common.BASE_PATH_TEX + "/*.png")
 30
 31    @classmethod
 32    def poll(cls, context):
 33        if hasattr(context, 'edit_image'):
 34            img = context.edit_image
 35            if img and (len(img.pixels) or img.source == 'VIEWER'):
 36                return True
 37        return False
 38
 39    def invoke(self, context, event):
 40        prefs = common.preferences()
 41        img = context.edit_image
 42        if img.filepath:
 43            prefs.tex_export_path = bpy.path.abspath(img.filepath)
 44        if prefs.tex_default_path:
 45            self.filepath = common.default_cm3d2_dir(prefs.tex_default_path, common.remove_serial_number(img.name), "tex")
 46        else:
 47            self.filepath = common.default_cm3d2_dir(prefs.tex_export_path, common.remove_serial_number(img.name), "tex")
 48        self.is_backup = bool(prefs.backup_ext)
 49        self.path = img.get('cm3d2_path')
 50        if self.path is None:
 51            self.path = common.get_tex_cm3d2path(self.filepath)
 52            img['cm3d2_path'] = self.path
 53
 54        if 'tex Name' in img:
 55            self.filepath = os.path.join(os.path.dirname(self.filepath), img['tex Name'])
 56        context.window_manager.fileselect_add(self)
 57        return {'RUNNING_MODAL'}
 58
 59    def draw(self, context):
 60        row = self.layout.row()
 61        row.prop(self, 'is_backup', icon='FILE_BACKUP')
 62        if not common.preferences().backup_ext:
 63            row.enabled = False
 64        self.layout.prop(self, 'version', icon='LINENUMBERS_ON')
 65        self.layout.prop(self, 'path', icon='ANIM')
 66
 67    def execute(self, context):
 68        common.preferences().tex_export_path = self.filepath
 69
 70        try:
 71            with common.open_temporary(self.filepath, 'wb', is_backup=self.is_backup) as file:
 72                version_num = int(self.version)
 73                self.write_texture(context, file, version_num)
 74            self.report(type={'INFO'}, message="texファイルを出力しました。" + self.filepath)
 75
 76        except common.CM3D2ExportException as e:
 77            self.report(type={'ERROR'}, message=str(e))
 78            return {'CANCELLED'}
 79        except Exception as e:
 80            self.report(type={'ERROR'}, message=f_tip_("texファイルの出力に失敗しました。{}", str(e)))
 81            return {'CANCELLED'}
 82
 83        return {'FINISHED'}
 84
 85    def write_texture(self, context, file, version):
 86        # とりあえずpngで保存
 87        img = context.edit_image
 88        if img.source != 'VIEWER':
 89            temp_path = self.filepath + ".temp.png"
 90        else:
 91            temp_path = os.path.splitext(self.filepath)[0] + ".png"
 92        pre_filepath = bpy.path.abspath(img.filepath)
 93        pre_source = img.source
 94        override = context.copy()
 95        override['edit_image'] = img
 96        try:
 97            save_as_render = True if pre_source == 'VIEWER' else False
 98            copy = True if pre_source == 'VIEWER' else False
 99            bpy.ops.image.save_as(override, save_as_render=save_as_render, copy=copy, filepath=temp_path, relative_path=True, show_multiview=False, use_multiview=False)
100            is_remove = True
101        except:
102            temp_path = bpy.path.abspath(img.filepath)
103            if os.path.exists(temp_path):
104                is_remove = False
105            else:
106                raise common.CM3D2ExportException("PNGファイルの取得に失敗しました")
107        if pre_source != 'VIEWER':
108            img.filepath = pre_filepath
109            img.source = pre_source
110
111        # pngバイナリを全て読み込み
112        with open(temp_path, 'rb') as temp_file:
113            temp_data = temp_file.read()
114        # 一時ファイルを削除
115        if is_remove:
116            os.remove(temp_path)
117
118        # 本命ファイルに書き込み
119        common.write_str(file, 'CM3D2_TEX')
120        file.write(struct.pack('<i', version))
121        common.write_str(file, self.path)
122        if version >= 1010:
123            if version >= 1011:
124                uv_rects = bpy.types.Scene.MyUVRects if hasattr(bpy.types.Scene, 'MyUVRects') else None
125                num_rects = len(uv_rects) if uv_rects else 0
126                file.write(struct.pack('<i', num_rects))
127                if num_rects > 0:
128                    for uv_rect in uv_rects:
129                        file.write( struct.pack('<4f', uv_rect[0], uv_rect[1], uv_rect[2], uv_rect[3]) )
130
131            width, height = img.size
132            file.write(struct.pack('<i', width))
133            file.write(struct.pack('<i', height))
134            file.write(struct.pack('<i', 5))  # tex_format TODO ダイアログで指定
135        file.write(struct.pack('<i', len(temp_data)))
136        file.write(temp_data)
137
138
139# メニューを登録する関数
140def menu_func(self, context):
141    self.layout.operator(CNV_OT_export_cm3d2_tex.bl_idname, icon_value=common.kiss_icon())
@compat.BlRegister()
class CNV_OT_export_cm3d2_tex(bpy_types.Operator):
 10@compat.BlRegister()
 11class CNV_OT_export_cm3d2_tex(bpy.types.Operator):
 12    bl_idname = 'image.export_cm3d2_tex'
 13    bl_label = "texファイルを保存"
 14    bl_description = "CM3D2で使用されるテクスチャファイル(.tex)として保存します"
 15    bl_options = {'REGISTER'}
 16
 17    filepath = bpy.props.StringProperty(subtype='FILE_PATH')
 18    filename_ext = ".tex"
 19    filter_glob = bpy.props.StringProperty(default="*.tex", options={'HIDDEN'})
 20
 21    is_backup = bpy.props.BoolProperty(name="ファイルをバックアップ", default=True, description="ファイルに上書きする場合にバックアップファイルを複製します")
 22
 23    version = bpy.props.EnumProperty(
 24        name="ファイルバージョン",
 25        items=[
 26            ('1011', '1011', 'COM3D2 1.13 or later', 'NONE', 0),
 27            ('1010', '1010', 'CM3D2 1.49 ~ or COM3D2', 'NONE', 1),
 28            ('1000', '1000', '旧フォーマット', 'NONE', 2),
 29        ], default='1010')
 30    path = bpy.props.StringProperty(name="パス", default=common.BASE_PATH_TEX + "/*.png")
 31
 32    @classmethod
 33    def poll(cls, context):
 34        if hasattr(context, 'edit_image'):
 35            img = context.edit_image
 36            if img and (len(img.pixels) or img.source == 'VIEWER'):
 37                return True
 38        return False
 39
 40    def invoke(self, context, event):
 41        prefs = common.preferences()
 42        img = context.edit_image
 43        if img.filepath:
 44            prefs.tex_export_path = bpy.path.abspath(img.filepath)
 45        if prefs.tex_default_path:
 46            self.filepath = common.default_cm3d2_dir(prefs.tex_default_path, common.remove_serial_number(img.name), "tex")
 47        else:
 48            self.filepath = common.default_cm3d2_dir(prefs.tex_export_path, common.remove_serial_number(img.name), "tex")
 49        self.is_backup = bool(prefs.backup_ext)
 50        self.path = img.get('cm3d2_path')
 51        if self.path is None:
 52            self.path = common.get_tex_cm3d2path(self.filepath)
 53            img['cm3d2_path'] = self.path
 54
 55        if 'tex Name' in img:
 56            self.filepath = os.path.join(os.path.dirname(self.filepath), img['tex Name'])
 57        context.window_manager.fileselect_add(self)
 58        return {'RUNNING_MODAL'}
 59
 60    def draw(self, context):
 61        row = self.layout.row()
 62        row.prop(self, 'is_backup', icon='FILE_BACKUP')
 63        if not common.preferences().backup_ext:
 64            row.enabled = False
 65        self.layout.prop(self, 'version', icon='LINENUMBERS_ON')
 66        self.layout.prop(self, 'path', icon='ANIM')
 67
 68    def execute(self, context):
 69        common.preferences().tex_export_path = self.filepath
 70
 71        try:
 72            with common.open_temporary(self.filepath, 'wb', is_backup=self.is_backup) as file:
 73                version_num = int(self.version)
 74                self.write_texture(context, file, version_num)
 75            self.report(type={'INFO'}, message="texファイルを出力しました。" + self.filepath)
 76
 77        except common.CM3D2ExportException as e:
 78            self.report(type={'ERROR'}, message=str(e))
 79            return {'CANCELLED'}
 80        except Exception as e:
 81            self.report(type={'ERROR'}, message=f_tip_("texファイルの出力に失敗しました。{}", str(e)))
 82            return {'CANCELLED'}
 83
 84        return {'FINISHED'}
 85
 86    def write_texture(self, context, file, version):
 87        # とりあえずpngで保存
 88        img = context.edit_image
 89        if img.source != 'VIEWER':
 90            temp_path = self.filepath + ".temp.png"
 91        else:
 92            temp_path = os.path.splitext(self.filepath)[0] + ".png"
 93        pre_filepath = bpy.path.abspath(img.filepath)
 94        pre_source = img.source
 95        override = context.copy()
 96        override['edit_image'] = img
 97        try:
 98            save_as_render = True if pre_source == 'VIEWER' else False
 99            copy = True if pre_source == 'VIEWER' else False
100            bpy.ops.image.save_as(override, save_as_render=save_as_render, copy=copy, filepath=temp_path, relative_path=True, show_multiview=False, use_multiview=False)
101            is_remove = True
102        except:
103            temp_path = bpy.path.abspath(img.filepath)
104            if os.path.exists(temp_path):
105                is_remove = False
106            else:
107                raise common.CM3D2ExportException("PNGファイルの取得に失敗しました")
108        if pre_source != 'VIEWER':
109            img.filepath = pre_filepath
110            img.source = pre_source
111
112        # pngバイナリを全て読み込み
113        with open(temp_path, 'rb') as temp_file:
114            temp_data = temp_file.read()
115        # 一時ファイルを削除
116        if is_remove:
117            os.remove(temp_path)
118
119        # 本命ファイルに書き込み
120        common.write_str(file, 'CM3D2_TEX')
121        file.write(struct.pack('<i', version))
122        common.write_str(file, self.path)
123        if version >= 1010:
124            if version >= 1011:
125                uv_rects = bpy.types.Scene.MyUVRects if hasattr(bpy.types.Scene, 'MyUVRects') else None
126                num_rects = len(uv_rects) if uv_rects else 0
127                file.write(struct.pack('<i', num_rects))
128                if num_rects > 0:
129                    for uv_rect in uv_rects:
130                        file.write( struct.pack('<4f', uv_rect[0], uv_rect[1], uv_rect[2], uv_rect[3]) )
131
132            width, height = img.size
133            file.write(struct.pack('<i', width))
134            file.write(struct.pack('<i', height))
135            file.write(struct.pack('<i', 5))  # tex_format TODO ダイアログで指定
136        file.write(struct.pack('<i', len(temp_data)))
137        file.write(temp_data)
bl_idname = 'image.export_cm3d2_tex'
bl_label = 'texファイルを保存'
bl_description = 'CM3D2で使用されるテクスチャファイル(.tex)として保存します'
bl_options = {'REGISTER'}
filepath: <_PropertyDeferred, <built-in function StringProperty>, {'subtype': 'FILE_PATH', 'attr': 'filepath'}> = <_PropertyDeferred, <built-in function StringProperty>, {'subtype': 'FILE_PATH', 'attr': 'filepath'}>
filename_ext = '.tex'
filter_glob: <_PropertyDeferred, <built-in function StringProperty>, {'default': '*.tex', 'options': {'HIDDEN'}, 'attr': 'filter_glob'}> = <_PropertyDeferred, <built-in function StringProperty>, {'default': '*.tex', 'options': {'HIDDEN'}, 'attr': 'filter_glob'}>
is_backup: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'ファイルをバックアップ', 'default': True, 'description': 'ファイルに上書きする場合にバックアップファイルを複製します', 'attr': 'is_backup'}> = <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'ファイルをバックアップ', 'default': True, 'description': 'ファイルに上書きする場合にバックアップファイルを複製します', 'attr': 'is_backup'}>
version: <_PropertyDeferred, <built-in function EnumProperty>, {'name': 'ファイルバージョン', 'items': [('1011', '1011', 'COM3D2 1.13 or later', 'NONE', 0), ('1010', '1010', 'CM3D2 1.49 ~ or COM3D2', 'NONE', 1), ('1000', '1000', '旧フォーマット', 'NONE', 2)], 'default': '1010', 'attr': 'version'}> = <_PropertyDeferred, <built-in function EnumProperty>, {'name': 'ファイルバージョン', 'items': [('1011', '1011', 'COM3D2 1.13 or later', 'NONE', 0), ('1010', '1010', 'CM3D2 1.49 ~ or COM3D2', 'NONE', 1), ('1000', '1000', '旧フォーマット', 'NONE', 2)], 'default': '1010', 'attr': 'version'}>
path: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'パス', 'default': 'Assets/texture/texture//*.png', 'attr': 'path'}> = <_PropertyDeferred, <built-in function StringProperty>, {'name': 'パス', 'default': 'Assets/texture/texture//*.png', 'attr': 'path'}>
@classmethod
def poll(cls, context):
32    @classmethod
33    def poll(cls, context):
34        if hasattr(context, 'edit_image'):
35            img = context.edit_image
36            if img and (len(img.pixels) or img.source == 'VIEWER'):
37                return True
38        return False
def invoke(self, context, event):
40    def invoke(self, context, event):
41        prefs = common.preferences()
42        img = context.edit_image
43        if img.filepath:
44            prefs.tex_export_path = bpy.path.abspath(img.filepath)
45        if prefs.tex_default_path:
46            self.filepath = common.default_cm3d2_dir(prefs.tex_default_path, common.remove_serial_number(img.name), "tex")
47        else:
48            self.filepath = common.default_cm3d2_dir(prefs.tex_export_path, common.remove_serial_number(img.name), "tex")
49        self.is_backup = bool(prefs.backup_ext)
50        self.path = img.get('cm3d2_path')
51        if self.path is None:
52            self.path = common.get_tex_cm3d2path(self.filepath)
53            img['cm3d2_path'] = self.path
54
55        if 'tex Name' in img:
56            self.filepath = os.path.join(os.path.dirname(self.filepath), img['tex Name'])
57        context.window_manager.fileselect_add(self)
58        return {'RUNNING_MODAL'}
def draw(self, context):
60    def draw(self, context):
61        row = self.layout.row()
62        row.prop(self, 'is_backup', icon='FILE_BACKUP')
63        if not common.preferences().backup_ext:
64            row.enabled = False
65        self.layout.prop(self, 'version', icon='LINENUMBERS_ON')
66        self.layout.prop(self, 'path', icon='ANIM')
def execute(self, context):
68    def execute(self, context):
69        common.preferences().tex_export_path = self.filepath
70
71        try:
72            with common.open_temporary(self.filepath, 'wb', is_backup=self.is_backup) as file:
73                version_num = int(self.version)
74                self.write_texture(context, file, version_num)
75            self.report(type={'INFO'}, message="texファイルを出力しました。" + self.filepath)
76
77        except common.CM3D2ExportException as e:
78            self.report(type={'ERROR'}, message=str(e))
79            return {'CANCELLED'}
80        except Exception as e:
81            self.report(type={'ERROR'}, message=f_tip_("texファイルの出力に失敗しました。{}", str(e)))
82            return {'CANCELLED'}
83
84        return {'FINISHED'}
def write_texture(self, context, file, version):
 86    def write_texture(self, context, file, version):
 87        # とりあえずpngで保存
 88        img = context.edit_image
 89        if img.source != 'VIEWER':
 90            temp_path = self.filepath + ".temp.png"
 91        else:
 92            temp_path = os.path.splitext(self.filepath)[0] + ".png"
 93        pre_filepath = bpy.path.abspath(img.filepath)
 94        pre_source = img.source
 95        override = context.copy()
 96        override['edit_image'] = img
 97        try:
 98            save_as_render = True if pre_source == 'VIEWER' else False
 99            copy = True if pre_source == 'VIEWER' else False
100            bpy.ops.image.save_as(override, save_as_render=save_as_render, copy=copy, filepath=temp_path, relative_path=True, show_multiview=False, use_multiview=False)
101            is_remove = True
102        except:
103            temp_path = bpy.path.abspath(img.filepath)
104            if os.path.exists(temp_path):
105                is_remove = False
106            else:
107                raise common.CM3D2ExportException("PNGファイルの取得に失敗しました")
108        if pre_source != 'VIEWER':
109            img.filepath = pre_filepath
110            img.source = pre_source
111
112        # pngバイナリを全て読み込み
113        with open(temp_path, 'rb') as temp_file:
114            temp_data = temp_file.read()
115        # 一時ファイルを削除
116        if is_remove:
117            os.remove(temp_path)
118
119        # 本命ファイルに書き込み
120        common.write_str(file, 'CM3D2_TEX')
121        file.write(struct.pack('<i', version))
122        common.write_str(file, self.path)
123        if version >= 1010:
124            if version >= 1011:
125                uv_rects = bpy.types.Scene.MyUVRects if hasattr(bpy.types.Scene, 'MyUVRects') else None
126                num_rects = len(uv_rects) if uv_rects else 0
127                file.write(struct.pack('<i', num_rects))
128                if num_rects > 0:
129                    for uv_rect in uv_rects:
130                        file.write( struct.pack('<4f', uv_rect[0], uv_rect[1], uv_rect[2], uv_rect[3]) )
131
132            width, height = img.size
133            file.write(struct.pack('<i', width))
134            file.write(struct.pack('<i', height))
135            file.write(struct.pack('<i', 5))  # tex_format TODO ダイアログで指定
136        file.write(struct.pack('<i', len(temp_data)))
137        file.write(temp_data)
bl_rna = <bpy_struct, Struct("IMAGE_OT_export_cm3d2_tex")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data